package com.qyl.framework.server.decoder;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qyl.framework.base.Message;
import com.qyl.framework.base.protocol.RequestProto;
import com.qyl.framework.utils.ParamsUtils;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

/**
 * 
 * @author created by 齐翌来（qiyilai@foxmail.com）
 * 
 * 2019年2月17日
 * 
 * @description
 * bytebuffer 解析成 classInfo
 * 
 * 2无符号字节  + 类名长度   + 2无符号 + 方法长度      + 参数个数 * (2无符号 + 类名长度 + 值)
 * 
 */
public class RequestProtoDecoder extends ByteToMessageDecoder {
	
	private Logger logger= LoggerFactory.getLogger(RequestProtoDecoder.class);

	@Override
	@SuppressWarnings("unchecked")
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
		logger.info("RequestProtoDecoder decode start");
		long requestId = in.readLong();
		int classNameLen = in.readByte();
		logger.info("request id={}", requestId);
		
		//Class解析
		byte classNameBytes[] = new byte[classNameLen];
		in.readBytes(classNameBytes);
		String className = new String(classNameBytes);
		
		//方法解析
		int methodNameLen = in.readByte();
		byte methodNameBytes[] = new byte[methodNameLen];
		in.readBytes(methodNameBytes);
		String methodName = new String(methodNameBytes);
		
		//执行参数
	    int paramLen = in.readByte();
	    Class<?>[] paramClasses = null;
	    Object[] params = null;
	    
	    if (paramLen != 0) {
	    	paramClasses = new Class<?>[paramLen];
		    params = new Object[paramLen];
		    
		    //解析参数
		    for (int i = 0 ; i < paramLen ; i++) {
		    	int paramClassLen = in.readByte();
		    	byte paramClass[] = new byte[paramClassLen];
		    	in.readBytes(paramClass);
		    	
		    	String paramType = new String(paramClass);
		    	Class<?> paramClassz = Class.forName(paramType);
		    	paramClasses[i] = paramClassz;
		    	
		    	if (paramClassz.isAssignableFrom(Message.class)) {
		    		Class<? extends Message> castClassz = (Class<? extends Message>)paramClassz;
		    		Message param = ParamsUtils.fromBuffer(in, castClassz);
		    		params[i] = param;
		    	} else if (isPrimitiveOrString(paramClassz)) {
		    		params[i] = ParamsUtils.fromBufferForSimpleType(in, paramClassz);
		    	} else {
		    		//非基本类 [byte, int, short, long, boolean, float, double], String , Message实现类，协议数据直接discard
		    		return;
		    	}
		    }
	    }
	    RequestProto classInfo = new RequestProto(requestId, className, methodName, paramClasses, params);
	    out.add(classInfo);
	}

	private boolean isPrimitiveOrString(Class<?> classz) {
		if (classz == Byte.class || classz == byte.class){
			return true;
		} else if (classz == Short.class || classz == short.class){
			return true;
		} else if (classz == Long.class || classz == Long.class){
			return true;
		} else if (classz == Boolean.class || classz == boolean.class){
			return true;
		} else if (classz == Float.class || classz == float.class){
			return true;
		} else if (classz == Double.class || classz == double.class){
			return true;
		} else if (classz == Character.class || classz == char.class){
			return true;
		} else if (classz == String.class){
			return true;
		}
		return false;
	}
}
